package com.design.pattern.factorymethod;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;

/**
 * Created by Administrator on 2016/5/17.
 */
public class ClassUtils {

    //给一个接口，返回这个接口的所有实现类
    public static List<Class> getAllClassByInterface(Class c){
        List<Class> classes = new ArrayList<Class>();
        if (c.isInterface()){
            String packageName = c.getPackage().getName();
            try {
                List<Class> allClasses = getClasses(packageName);
                for (int i = 0; i < allClasses.size(); i++) {
                    //判断是否是c的子类，或本身
                    if (c.isAssignableFrom(allClasses.get(i))){
                        if (!c.equals(allClasses.get(i))){
                            classes.add(allClasses.get(i));
                        }
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
        return classes;
    }

    private static List<Class> getClasses(String packageName) throws IOException, ClassNotFoundException {
        if (packageName == null) return null;
        List<Class> classes = new ArrayList<Class>();
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        String path = packageName.replace('.','/');
        Enumeration<URL> resources = classLoader.getResources(path);
        List<File> dirs = new ArrayList<File>();
        while (resources.hasMoreElements()){
            URL element = resources.nextElement();
            dirs.add(new File(element.getFile()));
        }
        for (File file : dirs){
            classes.addAll(findClassse(file, packageName));
        }
        return classes;
    }

    private static List<Class> findClassse(File directory,String packageName) throws ClassNotFoundException {
        List<Class> classes = new ArrayList<Class>();
        if (!directory.exists()){
            return classes;
        }
        File[] files = directory.listFiles();
        for (File file : files){
            if (file.isDirectory()){
                assert !file.getName().contains(".");
                classes.addAll(findClassse(file,packageName));
            }else{
                String fileName = file.getName();
                if (fileName.endsWith(".class")){
                    classes.add(Class.forName(packageName + fileName.substring(0, (fileName.length() - 6))));
                }
            }
        }
        return classes;
    }
}
